<template>
  <div
      id="cyDetailDialog"
      class="cy-detail-dialog"
      :style="dialogStyle"
      @mousedown="startDrag"
  >
    <div class="cy-dialog-header">
      <div class="cy-dialog-title">DOM元素详情</div>
      <button
          id="cyDetailDialogClose"
          class="cy-dialog-close"
          @click="close"
      >
        ✕✕
      </button>
    </div>

    <div class="cy-dialog-content">
      <div class="cy-tabs">
        <button
            v-for="tab in tabs"
            :key="tab.id"
            :class="['cy-tab-button', { active: activeTab === tab.id }]"
            @click="activeTab = tab.id"
        >
          {{ tab.label }}
        </button>
      </div>

      <div class="cy-tab-content">
        <template v-if="activeTab === 'properties'">
          <div class="cy-property-grid">
            <div class="cy-property-row" v-for="(value, key) in elementProperties" :key="key">
              <div class="cy-property-key">{{ key }}</div>
              <div class="cy-property-value">{{ value }}</div>
            </div>
          </div>
        </template>

        <template v-if="activeTab === 'html'">
          <div class="cy-code-container">
            <pre class="cy-code-block">{{ elementDetails.outerHTML }}</pre>
          </div>
        </template>

        <template v-if="activeTab === 'styles'">
          <div class="cy-styles-container">
            <div class="cy-style-section" v-for="(styles, category) in computedStyles" :key="category">
              <h4 class="cy-style-category">{{ category }}</h4>
              <div class="cy-style-grid">
                <div class="cy-style-item" v-for="(value, property) in styles" :key="property">
                  <span class="cy-style-property">{{ property }}:</span>
                  <span class="cy-style-value">{{ value }}</span>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>

    <div class="cy-dialog-footer">
      <button
          id="copyHtml"
          class="cy-btn cy-btn-secondary"
          @click="copyToClipboard(elementDetails.outerHTML, 'HTML')"
      >
        <i class="cy-icon-copy"></i> 复制HTML
      </button>
      <button
          id="copyText"
          class="cy-btn cy-btn-outline"
          @click="copyToClipboard(elementDetails.textContent, '文本')"
      >
        <i class="cy-icon-copy"></i> 复制文本
      </button>
      <button
          id="copyPath"
          class="cy-btn cy-btn-outline"
          @click="copyToClipboard(elementPath, '元素路径')"
      >
        <i class="cy-icon-copy"></i> 复制路径
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

const props = defineProps({
  element: {
    type: HTMLElement,
    required: true
  },
  position: {
    type: Object,
    default: () => ({ x: 0, y: 0 })
  }
})

const emit = defineEmits(['close'])

const tabs = [
  { id: 'properties', label: '属性' },
  { id: 'html', label: 'HTML' },
  { id: 'styles', label: '样式' }
]

const activeTab = ref('properties')
const isDragging = ref(false)
const dragStartPos = ref({ x: 0, y: 0 })
const dialogPos = ref({ x: props.position.x, y: props.position.y })

// 计算属性
const dialogStyle = computed(() => ({
  left: `${dialogPos.value.x}px`,
  top: `${dialogPos.value.y}px`,
  transform: dialogPos.value.x === 0 && dialogPos.value.y === 0 ? 'translate(-50%, -50%)' : 'none'
}))

const elementDetails = computed(() => {
  if (!props.element) return {}

  return {
    tagName: props.element.tagName,
    id: props.element.id || '无',
    className: props.element.className || '无',
    textContent: props.element.textContent.trim() || '无',
    innerHTML: props.element.innerHTML || '无',
    outerHTML: props.element.outerHTML || '无',
    nodeName: props.element.nodeName,
    nodeType: props.element.nodeType,
    nodeValue: props.element.nodeValue || '无',
    attributes: getAttributes(),
    boundingRect: props.element.getBoundingClientRect()
  }
})

const elementProperties = computed(() => {
  const details = elementDetails.value
  return {
    '标签名': details.tagName,
    'ID': details.id,
    '类名': details.className,
    '节点类型': `${details.nodeType} (${getNodeTypeName(details.nodeType)})`,
    '可见性': isElementVisible(props.element) ? '可见' : '隐藏',
    '尺寸': `${details.boundingRect.width.toFixed(1)}px × ${details.boundingRect.height.toFixed(1)}px`,
    '位置': `X: ${details.boundingRect.left.toFixed(1)}px, Y: ${details.boundingRect.top.toFixed(1)}px`,
    '子元素数': props.element.children ? props.element.children.length : 0
  }
})

const elementPath = computed(() => {
  return getElementPath(props.element)
})

const computedStyles = computed(() => {
  if (!props.element) return {}

  const styles = window.getComputedStyle(props.element)
  const styleGroups = {
    '布局': {},
    '文字': {},
    '背景': {},
    '边框': {},
    '其他': {}
  }

  // 分类样式属性
  for (let i = 0; i < styles.length; i++) {
    const prop = styles[i]
    const value = styles.getPropertyValue(prop)

    if (prop.startsWith('margin') || prop.startsWith('padding') || prop.includes('width') || prop.includes('height')) {
      styleGroups['布局'][prop] = value
    }
    else if (prop.includes('color') || prop.includes('font') || prop.includes('text')) {
      styleGroups['文字'][prop] = value
    }
    else if (prop.includes('background')) {
      styleGroups['背景'][prop] = value
    }
    else if (prop.includes('border')) {
      styleGroups['边框'][prop] = value
    }
    else {
      styleGroups['其他'][prop] = value
    }
  }

  return styleGroups
})

// 方法
function getAttributes() {
  if (!props.element || !props.element.attributes) return []

  return Array.from(props.element.attributes).map(attr => ({
    name: attr.name,
    value: attr.value
  }))
}

function getNodeTypeName(type) {
  const nodeTypes = {
    1: '元素节点',
    2: '属性节点',
    3: '文本节点',
    4: 'CDATA节点',
    5: '实体引用节点',
    6: '实体节点',
    7: '处理指令节点',
    8: '注释节点',
    9: '文档节点',
    10: '文档类型节点',
    11: '文档片段节点'
  }
  return nodeTypes[type] || '未知类型'
}

function isElementVisible(el) {
  if (!el) return false
  return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)
}

function getElementPath(element) {
  if (!element || !element.tagName) return ''

  const path = []
  let current = element

  while (current && current.tagName && current.tagName.toLowerCase() !== 'html') {
    let selector = current.tagName.toLowerCase()

    if (current.id) {
      selector += `#${current.id}`
      path.unshift(selector)
      break
    } else {
      let sibling = current
      let nth = 1

      while (sibling.previousElementSibling) {
        sibling = sibling.previousElementSibling
        nth++
      }

      if (current.className) {
        selector += `.${current.className.split(' ').join('.')}`
      }

      selector += `:nth-child(${nth})`
      path.unshift(selector)
    }

    current = current.parentNode
  }

  return path.join(' > ')
}

function copyToClipboard(content, type = '内容') {
  navigator.clipboard.writeText(content)
      .then(() => {
        GM_notification({
          title: '复制成功',
          text: `${type}已复制到剪贴板`,
          timeout: 2000
        })
      })
      .catch(err => {
        console.error('复制失败:', err)
        fallbackCopy(content, type)
      })
}

function fallbackCopy(content, type) {
  const textarea = document.createElement('textarea')
  textarea.value = content
  document.body.appendChild(textarea)
  textarea.select()

  try {
    document.execCommand('copy')
    GM_notification({
      title: '复制成功',
      text: `${type}已复制到剪贴板`,
      timeout: 2000
    })
  } catch (err) {
    GM_notification({
      title: '复制失败',
      text: '请手动复制文本',
      timeout: 2000
    })
  }

  document.body.removeChild(textarea)
}

function startDrag(e) {
  if (e.target.classList.contains('cy-dialog-close')) return

  isDragging.value = true
  dragStartPos.value = {
    x: e.clientX - dialogPos.value.x,
    y: e.clientY - dialogPos.value.y
  }

  document.addEventListener('mousemove', handleDrag)
  document.addEventListener('mouseup', stopDrag)
  e.preventDefault()
}

function handleDrag(e) {
  if (!isDragging.value) return

  dialogPos.value = {
    x: e.clientX - dragStartPos.value.x,
    y: e.clientY - dragStartPos.value.y
  }
}

function stopDrag() {
  isDragging.value = false
  document.removeEventListener('mousemove', handleDrag)
  document.removeEventListener('mouseup', stopDrag)
}

function close() {
  emit('close')
}

onMounted(() => {
  // 初始化对话框位置
  if (props.position.x !== 0 || props.position.y !== 0) {
    dialogPos.value = props.position
  }
})
</script>

<style scoped>
.cy-detail-dialog {
  position: fixed;
  width: 800px;
  max-width: 90vw;
  max-height: 80vh;
  background: var(--glass-bg);
  border-radius: 12px;
  box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
  z-index: 10000;
  border: var(--neon-border);
  backdrop-filter: blur(10px);
  color: var(--text-primary);
  font-family: var(--cyber-font);
  display: flex;
  flex-direction: column;
}

.cy-dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  cursor: move;
  user-select: none;
}

.cy-dialog-title {
  font-size: 18px;
  font-weight: bold;
  background: var(--secondary-gradient);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.cy-dialog-close {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 20px;
  cursor: pointer;
  transition: var(--transition);
  padding: 5px;
}

.cy-dialog-close:hover {
  color: var(--text-primary);
  transform: rotate(90deg);
}

.cy-dialog-content {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.cy-tabs {
  display: flex;
  padding: 0 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.cy-tab-button {
  padding: 10px 20px;
  background: none;
  border: none;
  cursor: pointer;
  position: relative;
  color: var(--text-secondary);
  font-family: var(--cyber-font);
  transition: var(--transition);
}

.cy-tab-button:hover {
  color: var(--text-primary);
}

.cy-tab-button.active {
  color: var(--text-primary);
}

.cy-tab-button.active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--primary-gradient);
  transition: var(--transition);
}

.cy-tab-content {
  flex: 1;
  overflow: auto;
  padding: 20px;
}

.cy-property-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 10px 15px;
}

.cy-property-row {
  display: contents;
}

.cy-property-key {
  color: var(--text-secondary);
  font-weight: bold;
}

.cy-property-value {
  word-break: break-word;
}

.cy-code-container {
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
  padding: 15px;
  overflow: auto;
}

.cy-code-block {
  margin: 0;
  white-space: pre-wrap;
  font-family: 'Fira Code', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.cy-styles-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.cy-style-section {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 6px;
  padding: 15px;
}

.cy-style-category {
  margin-top: 0;
  margin-bottom: 10px;
  color: #60efff;
}

.cy-style-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}

.cy-style-item {
  display: flex;
  gap: 5px;
}

.cy-style-property {
  color: #00ff87;
}

.cy-style-value {
  word-break: break-all;
}

.cy-dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 15px 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.cy-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-family: var(--cyber-font);
  font-weight: bold;
  transition: var(--transition);
  display: flex;
  align-items: center;
  gap: 8px;
}

.cy-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.cy-btn-secondary {
  background: var(--secondary-gradient);
  color: white;
}

.cy-btn-outline {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: var(--text-primary);
}

.cy-icon-copy {
  display: inline-block;
  width: 16px;
  height: 16px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='currentColor'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3' /%3E%3C/svg%3E");
  background-size: contain;
}

@media (max-width: 768px) {
  .cy-detail-dialog {
    width: 95vw;
    padding: 15px;
  }

  .cy-tabs {
    flex-wrap: wrap;
  }

  .cy-tab-button {
    padding: 8px 12px;
    font-size: 14px;
  }

  .cy-property-grid {
    grid-template-columns: 1fr;
  }

  .cy-property-row {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-bottom: 10px;
  }

  .cy-dialog-footer {
    flex-wrap: wrap;
    justify-content: center;
  }
}
</style>
